package com.xyh.builder;

import com.xyh.bean.Constants;
import com.xyh.bean.FieldInfo;
import com.xyh.bean.TableInfo;
import com.xyh.utils.DateUtils;
import com.xyh.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * @Author: Hendrix Xie
 * @CreateTime: 2025-03-23 01:00:36
 * @Description: Service层生成器
 * @Version: 1.0
 */
public class BuildService {
    private static final Logger logger = LoggerFactory.getLogger(BuildService.class);

    public static void execute(TableInfo tableInfo) {
        // 初始化目录和文件
        File serviceDir = new File(Constants.PATH_SERVICE);
        if (!serviceDir.exists() && !serviceDir.mkdirs()) {
            logger.error("创建Service目录失败: {}", Constants.PATH_SERVICE);
            return;
        }

        File serviceFile = new File(serviceDir, tableInfo.getBeanName() + Constants.SUFFIX_SERVICE + ".java");

        // 生成Service类
        try (BufferedWriter bw = new BufferedWriter(
                new OutputStreamWriter(new FileOutputStream(serviceFile), StandardCharsets.UTF_8))) {
            writePackage(bw); // 包声明
            writeImports(bw, tableInfo); // 导包区域
            writeClassComment(bw, tableInfo); // 类注释
            writeClassDefinition(bw, tableInfo); // 类定义
            writeMethods(bw, tableInfo); // 方法生成
            bw.write("}");
            bw.flush();
            logger.info("生成Service成功: {}", serviceFile.getAbsolutePath());
        } catch (Exception e) {
            logger.error("生成Service失败: 表名={}", tableInfo.getTableName(), e);
        }
    }

    private static void writeMethods(BufferedWriter bw, TableInfo tableInfo) throws IOException {
        // 根据条件查询列表
        writeMethodComment(bw, "根据条件查询列表");
        generateFindListByParam(bw, tableInfo);
        // 根据条件查询数量
        writeMethodComment(bw, "根据条件查询数量");
        generateFindListCountByParam(bw, tableInfo);
        // 分页查询
        writeMethodComment(bw, "分页查询");
        generateFindListByParamAndPage(bw, tableInfo);
        // 新增
        writeMethodComment(bw, "新增");
        generateAdd(bw, tableInfo);
        // 批量新增
        writeMethodComment(bw, "批量新增");
        generateBatchAdd(bw, tableInfo);
        // 批量新增/修改
        writeMethodComment(bw, "批量新增/修改");
        generateBatchAddOrUpdate(bw, tableInfo);

        // 查主键逻辑
        Set<String> keyFieldNameSet = new HashSet<>();
        for (Map.Entry<String, List<FieldInfo>> entry : tableInfo.getKeyIndexMap().entrySet()) {
            List<FieldInfo> keyFieldList = entry.getValue();
            Integer index = 0;
            StringBuffer methodName = new StringBuffer();
            StringBuffer methodParams = new StringBuffer();
            for (FieldInfo fieldInfo : keyFieldList) {
                index++;
                methodName.append(StringUtils.upperCaseFirstLetter(fieldInfo.getPropertyName()));
                if (index < keyFieldList.size()) {
                    methodName.append("And");
                }
                methodParams.append(fieldInfo.getJavaType() + " " + fieldInfo.getPropertyName());
                if (index < keyFieldList.size()) {
                    methodParams.append(",");
                }
                keyFieldNameSet.add(fieldInfo.getPropertyName());
            }

            writeMethodComment(bw, "根据" + methodName + "查询");
            bw.write("\t" + tableInfo.getBeanName() + " findBy" + methodName + "(" + methodParams + ");");
            bw.newLine();
            bw.newLine();

            writeMethodComment(bw, "根据" + methodName + "修改");
            bw.write("\tLong updateBy" + methodName + "(" + tableInfo.getBeanName() + " entity, " + methodParams + ");");
            bw.newLine();
            bw.newLine();

            writeMethodComment(bw, "根据" + methodName + "删除");
            bw.write("\tLong deleteBy" + methodName + "(" + methodParams + ");");
            bw.newLine();
            bw.newLine();
        }
        //根据id删除
        for (FieldInfo fieldInfo : tableInfo.getFieldList()) {
            if(!keyFieldNameSet.contains(fieldInfo.getPropertyName()) && fieldInfo.getPropertyName().toLowerCase().endsWith("id")){
                writeMethodComment(bw, "根据"+fieldInfo.getPropertyName() + "删除");
                bw.write("\tLong deleteBy"+StringUtils.upperCaseFirstLetter(fieldInfo.getPropertyName())+"("+fieldInfo.getJavaType() + " " + fieldInfo.getPropertyName()+");");
                bw.newLine();
            }
        }
    }

    private static void generateBatchAddOrUpdate(BufferedWriter bw, TableInfo tableInfo) throws IOException {
        bw.write("\tLong batchAddOrUpdate(List<" + tableInfo.getBeanName() + "> list);\n");
    }

    private static void generateBatchAdd(BufferedWriter bw, TableInfo tableInfo) throws IOException {
        bw.write("\tLong batchAdd(List<" + tableInfo.getBeanName() + "> list);\n");
    }

    private static void generateAdd(BufferedWriter bw, TableInfo tableInfo) throws IOException {
        bw.write("\tLong add(" + tableInfo.getBeanName() + " bean);\n");
    }

    private static void generateFindListByParamAndPage(BufferedWriter bw, TableInfo tableInfo) throws IOException {
        bw.write("\tPaginationResultVO<" + tableInfo.getBeanName() + "> findListByPage(" + tableInfo.getBeanParamName() + " param);\n");
    }

    private static void generateFindListCountByParam(BufferedWriter bw, TableInfo tableInfo) throws IOException {
        bw.write("\tLong findCountByParam(" + tableInfo.getBeanParamName() + " param);\n");
    }

    private static void generateFindListByParam(BufferedWriter bw, TableInfo tableInfo) throws IOException {
        bw.write("\tList<" + tableInfo.getBeanName() + "> findListByParam(" + tableInfo.getBeanParamName() + " param);\n");
    }

    private static void writeMethodComment(BufferedWriter bw, String comment) throws IOException {
        bw.write("\t/** ");
        bw.newLine();
        if (comment != null && !comment.isEmpty()) {
            bw.write("\t * " + comment);
            bw.newLine();
        } else {
            bw.write("\t * ");
            bw.newLine();
        }
        bw.write("\t */");
        bw.newLine();
    }

    private static void writeClassDefinition(BufferedWriter bw, TableInfo tableInfo) throws IOException {
        bw.write("public interface " + tableInfo.getBeanName() + Constants.SUFFIX_SERVICE + " {\n");
    }

    private static void writeClassComment(BufferedWriter bw, TableInfo tableInfo) throws IOException {
        bw.write("/**");
        bw.newLine();
        bw.write(" * " + (null != tableInfo.getComment() ? tableInfo.getComment() : tableInfo.getBeanName()) + " 业务接口");
        bw.newLine();
        bw.write(" * ");
        bw.newLine();
        bw.write(" * 对应数据库表: " + tableInfo.getTableName());
        bw.newLine();
        bw.write(" * @author " + Constants.AUTHOR);
        bw.newLine();
        bw.write(" * @date " + DateUtils.format(new Date(), DateUtils.YYYY_MM_DD_HH_MM_SS));
        bw.newLine();
        bw.write(" */");
        bw.newLine();
    }

    private static void writeImports(BufferedWriter bw, TableInfo tableInfo) throws IOException {
        writeBasicImports(bw, tableInfo);
    }

    private static void writeBasicImports(BufferedWriter bw, TableInfo tableInfo) throws IOException {
        String[] imports = {
                "java.util.List",
                Constants.PACKAGE_PO + "." + tableInfo.getBeanName(),
                Constants.PACKAGE_PARAM + "." + tableInfo.getBeanParamName(),
                Constants.PACKAGE_VO + "." + "PaginationResultVO",
        };

        for (String imp : imports) {
            bw.write("import " + imp + ";");
            bw.newLine();
        }
    }

    private static void writePackage(BufferedWriter bw) throws IOException {
        bw.write("package " + Constants.PACKAGE_SERVICE + ";");
        bw.newLine();
        bw.newLine();
    }
}